From c3b38c784693b925dce18da27d2f4f71495d2e0a Mon Sep 17 00:00:00 2001 From: "cl349@freefall.cl.cam.ac.uk" Date: Wed, 8 Sep 2004 09:49:46 +0000 Subject: [PATCH] bitkeeper revision 1.1159.1.136 (413ed5baHUBJ5EA2PO0yZ_45_I8a5w) g/c support for multiple inactive writable pagetables. Also use consistent names for bookkeeping data. --- xen/arch/x86/memory.c | 151 +++++++++++++++++++-------------------- xen/arch/x86/traps.c | 5 +- xen/include/asm-x86/mm.h | 30 ++++---- 3 files changed, 89 insertions(+), 97 deletions(-) diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index 08dd76c7bf..f140c6ce44 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1486,8 +1486,8 @@ int do_update_va_mapping_otherdomain(unsigned long page_nr, ptwr_info_t ptwr_info[NR_CPUS] = { [ 0 ... NR_CPUS-1 ] = { - .disconnected = ENTRIES_PER_L2_PAGETABLE, - .writable_idx = 0, + .disconnected_pteidx = -1, + .writable_l1va = 0, } }; @@ -1498,7 +1498,7 @@ int ptwr_debug = 0; #define PTWR_PRINTK(x) #endif -void ptwr_reconnect_disconnected(unsigned long addr) +void ptwr_reconnect_disconnected(void) { unsigned long pte; unsigned long pfn; @@ -1508,11 +1508,11 @@ void ptwr_reconnect_disconnected(unsigned long addr) int cpu = smp_processor_id(); int i; unsigned long *writable_pte = (unsigned long *)&linear_pg_table - [ptwr_info[cpu].writable_l1>>PAGE_SHIFT]; + [ptwr_info[cpu].disconnected_l1va>>PAGE_SHIFT]; - PTWR_PRINTK(("[A] page fault in disconn space: addr %08lx space %08lx\n", - addr, ptwr_info[cpu].disconnected << L2_PAGETABLE_SHIFT)); - pl2e = &linear_l2_table[ptwr_info[cpu].disconnected]; + PTWR_PRINTK(("[A] page fault in disconn space %08lx\n", + ptwr_info[cpu].disconnected_pteidx << L2_PAGETABLE_SHIFT)); + pl2e = &linear_l2_table[ptwr_info[cpu].disconnected_pteidx]; if (__get_user(pte, writable_pte)) { MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); @@ -1558,21 +1558,21 @@ void ptwr_reconnect_disconnected(unsigned long addr) frame_table[pfn].u.inuse.type_info, frame_table[pfn].count_info, frame_table[pfn].u.inuse.domain->domain)); - ptwr_info[cpu].disconnected = ENTRIES_PER_L2_PAGETABLE; + ptwr_info[cpu].disconnected_pteidx = -1; /* make pt page write protected */ if (__get_user(pte, writable_pte)) { MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); domain_crash(); } - PTWR_PRINTK(("[A] writable_l1 at %p is %08lx\n", + PTWR_PRINTK(("[A] disconnected_l1va at %p is %08lx\n", writable_pte, pte)); pte &= ~_PAGE_RW; if (__put_user(pte, writable_pte)) { MEM_LOG("ptwr: Could not update pte at %p\n", writable_pte); domain_crash(); } - __flush_tlb_one(ptwr_info[cpu].writable_l1); - PTWR_PRINTK(("[A] writable_l1 at %p now %08lx\n", + __flush_tlb_one(ptwr_info[cpu].disconnected_l1va); + PTWR_PRINTK(("[A] disconnected_l1va at %p now %08lx\n", writable_pte, pte)); /* and try again */ return; @@ -1584,48 +1584,47 @@ void ptwr_flush_inactive(void) struct pfn_info *page; l1_pgentry_t *pl1e; int cpu = smp_processor_id(); - int i, idx; + int i; - for (idx = 0; idx < ptwr_info[cpu].writable_idx; idx++) { - unsigned long *writable_pte = (unsigned long *)&linear_pg_table - [ptwr_info[cpu].writables[idx]>>PAGE_SHIFT]; - if (__get_user(pte, writable_pte)) { - MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); - domain_crash(); - } - pfn = pte >> PAGE_SHIFT; - page = &frame_table[pfn]; - PTWR_PRINTK(("[I] alloc l1 page %p\n", page)); - - pl1e = map_domain_mem(pfn << PAGE_SHIFT); - for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) { - l1_pgentry_t ol1e, nl1e; - ol1e = ptwr_info[cpu].writable_page[idx][i]; - nl1e = pl1e[i]; - if (likely(l1_pgentry_val(ol1e) == l1_pgentry_val(nl1e))) - continue; - if (unlikely(l1_pgentry_val(ol1e) & _PAGE_PRESENT)) - put_page_from_l1e(ol1e, current); - if (unlikely(!get_page_from_l1e(nl1e, current))) { - MEM_LOG("ptwr: Could not re-validate l1 page\n"); - domain_crash(); - } - } - unmap_domain_mem(pl1e); - - /* make pt page writable */ - PTWR_PRINTK(("[I] writable_l1 at %p is %08lx\n", - writable_pte, pte)); - pte &= ~_PAGE_RW; - if (__put_user(pte, writable_pte)) { - MEM_LOG("ptwr: Could not update pte at %p\n", writable_pte); + unsigned long *writable_pte = (unsigned long *)&linear_pg_table + [ptwr_info[cpu].writable_l1va>>PAGE_SHIFT]; + if (__get_user(pte, writable_pte)) { + MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); + domain_crash(); + } + pfn = pte >> PAGE_SHIFT; + page = &frame_table[pfn]; + PTWR_PRINTK(("[I] alloc l1 page %p\n", page)); + + pl1e = map_domain_mem(pfn << PAGE_SHIFT); + for ( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) { + l1_pgentry_t ol1e, nl1e; + ol1e = ptwr_info[cpu].writable_page[i]; + nl1e = pl1e[i]; + if (likely(l1_pgentry_val(ol1e) == l1_pgentry_val(nl1e))) + continue; + if (unlikely(l1_pgentry_val(ol1e) & _PAGE_PRESENT)) + put_page_from_l1e(ol1e, current); + if (unlikely(!get_page_from_l1e(nl1e, current))) { + MEM_LOG("ptwr: Could not re-validate l1 page\n"); domain_crash(); } - __flush_tlb_one(ptwr_info[cpu].writables[idx]); - PTWR_PRINTK(("[I] writable_l1 at %p now %08lx\n", - writable_pte, pte)); } - ptwr_info[cpu].writable_idx = 0; + unmap_domain_mem(pl1e); + + /* make pt page writable */ + PTWR_PRINTK(("[I] disconnected_l1va at %p is %08lx\n", + writable_pte, pte)); + pte &= ~_PAGE_RW; + if (__put_user(pte, writable_pte)) { + MEM_LOG("ptwr: Could not update pte at %p\n", writable_pte); + domain_crash(); + } + __flush_tlb_one(ptwr_info[cpu].writable_l1va); + PTWR_PRINTK(("[I] disconnected_l1va at %p now %08lx\n", + writable_pte, pte)); + + ptwr_info[cpu].writable_l1va = 0; } int ptwr_do_page_fault(unsigned long addr) @@ -1669,24 +1668,21 @@ int ptwr_do_page_fault(unsigned long addr) PTWR_PRINTK(("[I] freeing l1 page %p taf %08x/%08x\n", page, page->u.inuse.type_info, page->count_info)); - if (ptwr_info[cpu].writable_idx == PTWR_NR_WRITABLES) + if (ptwr_info[cpu].writable_l1va) ptwr_flush_inactive(); - ptwr_info[cpu].writables[ptwr_info[cpu].writable_idx] = addr; + ptwr_info[cpu].writable_l1va = addr | 1; pl1e = map_domain_mem(pfn << PAGE_SHIFT); - memcpy(&ptwr_info[cpu].writable_page[ - ptwr_info[cpu].writable_idx][0], + memcpy(&ptwr_info[cpu].writable_page[0], pl1e, ENTRIES_PER_L1_PAGETABLE * sizeof(l1_pgentry_t)); unmap_domain_mem(pl1e); - - ptwr_info[cpu].writable_idx++; } else { l2_pgentry_t nl2e; l1_pgentry_t *pl1e; - if ( ptwr_info[cpu].disconnected != ENTRIES_PER_L2_PAGETABLE ) - ptwr_reconnect_disconnected(addr); + if ( ptwr_info[cpu].disconnected_pteidx >= 0 ) + ptwr_reconnect_disconnected(); PTWR_PRINTK(("[A] pl2e %p l2e %08lx pfn %08lx " "taf %08x/%08x/%u\n", pl2e, l2_pgentry_val(*pl2e), l1_pgentry_val(linear_pg_table[(unsigned long)pl2e @@ -1699,14 +1695,14 @@ int ptwr_do_page_fault(unsigned long addr) nl2e = mk_l2_pgentry((l2_pgentry_val(*pl2e) & ~_PAGE_PRESENT)); update_l2e(pl2e, *pl2e, nl2e); - ptwr_info[cpu].disconnected = + ptwr_info[cpu].disconnected_pteidx = (page->u.inuse.type_info & PGT_va_mask) >> PGT_va_shift; PTWR_PRINTK(("[A] now pl2e %p l2e %08lx " "taf %08x/%08x/%u\n", pl2e, l2_pgentry_val(*pl2e), frame_table[pfn].u.inuse.type_info, frame_table[pfn].count_info, frame_table[pfn].u.inuse.domain->domain)); - ptwr_info[cpu].writable_l1 = addr; + ptwr_info[cpu].disconnected_l1va = addr; pl1e = map_domain_mem(l2_pgentry_to_pagenr(nl2e) << PAGE_SHIFT); memcpy(&ptwr_info[cpu].disconnected_page[0], pl1e, @@ -1739,34 +1735,31 @@ void ptwr_status(void) l2_pgentry_t *pl2e; int cpu = smp_processor_id(); - for ( i = 0; i < ptwr_info[cpu].writable_idx; i++ ) - { - unsigned long *writable_pte = (unsigned long *)&linear_pg_table - [ptwr_info[cpu].writables[i]>>PAGE_SHIFT]; - - if ( __get_user(pte, writable_pte) ) { - MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); - domain_crash(); - } + unsigned long *writable_pte = (unsigned long *)&linear_pg_table + [ptwr_info[cpu].writable_l1va>>PAGE_SHIFT]; - pfn = pte >> PAGE_SHIFT; - page = &frame_table[pfn]; - printk("need to alloc l1 page %p\n", page); - /* make pt page writable */ - printk("need to make read-only l1-page at %p is %08lx\n", - writable_pte, pte); + if ( __get_user(pte, writable_pte) ) { + MEM_LOG("ptwr: Could not read pte at %p\n", writable_pte); + domain_crash(); } - if ( ptwr_info[cpu].disconnected == ENTRIES_PER_L2_PAGETABLE ) + pfn = pte >> PAGE_SHIFT; + page = &frame_table[pfn]; + printk("need to alloc l1 page %p\n", page); + /* make pt page writable */ + printk("need to make read-only l1-page at %p is %08lx\n", + writable_pte, pte); + + if ( ptwr_info[cpu].disconnected_pteidx < 0 ) return; printk("disconnected space: space %08lx\n", - ptwr_info[cpu].disconnected << L2_PAGETABLE_SHIFT); - pl2e = &linear_l2_table[ptwr_info[cpu].disconnected]; + ptwr_info[cpu].disconnected_pteidx << L2_PAGETABLE_SHIFT); + pl2e = &linear_l2_table[ptwr_info[cpu].disconnected_pteidx]; - if ( __get_user(pte, (unsigned long *)ptwr_info[cpu].writable_l1) ) { + if ( __get_user(pte, (unsigned long *)ptwr_info[cpu].disconnected_l1va) ) { MEM_LOG("ptwr: Could not read pte at %p\n", (unsigned long *) - ptwr_info[cpu].writable_l1); + ptwr_info[cpu].disconnected_l1va); domain_crash(); } pfn = pte >> PAGE_SHIFT; diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index c0c1a41e23..800e66df1a 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -351,9 +351,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) ) { - if ( unlikely((addr >> L2_PAGETABLE_SHIFT) == ptwr_info[cpu].disconnected )) + if ( unlikely((addr >> L2_PAGETABLE_SHIFT) == + ptwr_info[cpu].disconnected_pteidx )) { - ptwr_reconnect_disconnected(addr); + ptwr_reconnect_disconnected(); return; } diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 09005b318f..c300ef57bd 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -370,14 +370,12 @@ extern vm_assist_info_t vm_assist_info[]; /* Writable Pagetables */ -#define PTWR_NR_WRITABLES 1 typedef struct { - unsigned long disconnected; + long disconnected_pteidx; l1_pgentry_t disconnected_page[ENTRIES_PER_L1_PAGETABLE]; - unsigned long writable_l1; - unsigned long writables[PTWR_NR_WRITABLES]; - int writable_idx; - l1_pgentry_t writable_page[PTWR_NR_WRITABLES][ENTRIES_PER_L1_PAGETABLE]; + unsigned long disconnected_l1va; + unsigned long writable_l1va; + l1_pgentry_t writable_page[ENTRIES_PER_L1_PAGETABLE]; } __cacheline_aligned ptwr_info_t; extern ptwr_info_t ptwr_info[]; @@ -385,19 +383,19 @@ extern ptwr_info_t ptwr_info[]; #define PTWR_CLEANUP_ACTIVE 1 #define PTWR_CLEANUP_INACTIVE 2 -void ptwr_reconnect_disconnected(unsigned long addr); +void ptwr_reconnect_disconnected(void); void ptwr_flush_inactive(void); int ptwr_do_page_fault(unsigned long); -#define __cleanup_writable_pagetable(_what) \ -do { \ - int cpu = smp_processor_id(); \ - if ((_what) & PTWR_CLEANUP_ACTIVE) \ - if (ptwr_info[cpu].disconnected != ENTRIES_PER_L2_PAGETABLE) \ - ptwr_reconnect_disconnected(0L); \ - if ((_what) & PTWR_CLEANUP_INACTIVE) \ - if (ptwr_info[cpu].writable_idx) \ - ptwr_flush_inactive(); \ +#define __cleanup_writable_pagetable(_what) \ +do { \ + int cpu = smp_processor_id(); \ + if ((_what) & PTWR_CLEANUP_ACTIVE) \ + if (ptwr_info[cpu].disconnected_pteidx >= 0) \ + ptwr_reconnect_disconnected(); \ + if ((_what) & PTWR_CLEANUP_INACTIVE) \ + if (ptwr_info[cpu].writable_l1va) \ + ptwr_flush_inactive(); \ } while ( 0 ) #define cleanup_writable_pagetable(_d, _w) \ -- 2.30.2